package com.cocotingo.snail.template.models;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.cocotingo.snail.template.TemplateSyntaxException;
import com.cocotingo.snail.template.XMLTemplateParser;

public class TemplateDefinitionsNode extends Node {
	
	private String version;
	private final List<ImportNode> imports;
	private final List<ResourceNode> resources;
	private final List<TemplateNode> templates;
	
	public TemplateDefinitionsNode() {
		version = XMLTemplateParser.VERSION;
		imports = new ArrayList<ImportNode>();
		resources = new ArrayList<ResourceNode>();
		templates = new ArrayList<TemplateNode>();
	}
	
	public String getVersion() {
		return version;
	}
	
	public void setVersion(String version) {
		this.version = version;
	}
	
	public final void addImportNode(ImportNode node) {
		this.addImportNode(node, imports.size());
	}
	
	public void addImportNode(ImportNode node, int index) {
		if (node == null) throw new IllegalArgumentException("cannot add null as a child node");
		imports.add(index, node);
	}
	
	public boolean removeImportNode(ImportNode node) {
		return imports.remove(node);
	}
	
	public Iterable<ImportNode> importNodes() {
		return new Iterable<ImportNode>() {
			@Override
			public Iterator<ImportNode> iterator() {
				return imports.iterator();
			}
		};
	}
	
	public int importNodeCount() {
		return imports.size();
	}
	
	public final void addResourceNode(ResourceNode node) {
		this.addResourceNode(node, resources.size());
	}
	
	public void addResourceNode(ResourceNode node, int index) {
		if (node == null) throw new IllegalArgumentException("cannot add null as a child node");
		resources.add(index, node);
	}
	
	public boolean removeResourceNode(ResourceNode node) {
		return resources.remove(node);
	}
	
	public Iterable<ResourceNode> resourceNodes() {
		return new Iterable<ResourceNode>() {
			@Override
			public Iterator<ResourceNode> iterator() {
				return resources.iterator();
			}
		};
	}
	
	public int resourceNodeCount() {
		return resources.size();
	}
	
	public final void addTemplateNode(TemplateNode node) {
		this.addTemplateNode(node, templates.size());
	}
	
	public void addTemplateNode(TemplateNode node, int index) {
		if (node == null) throw new IllegalArgumentException("cannot add null as a child node");
		templates.add(index, node);
	}
	
	public boolean removeTemplateNode(TemplateNode node) {
		return templates.remove(node);
	}
	
	public Iterable<TemplateNode> templateNodes() {
		return new Iterable<TemplateNode>() {
			@Override
			public Iterator<TemplateNode> iterator() {
				return templates.iterator();
			}
		};
	}
	
	public int templateNodeCount() {
		return templates.size();
	}

	@Override
	public void validateNode() throws TemplateSyntaxException {
		if (version == null || version.isEmpty()) throw new TemplateSyntaxException(this, "TemplateDefinitionsNode.version shouldn't be empty/null.");
	}
	
	@Override
	public Iterable<Node> children() {
		return new Iterable<Node>() {
			int it = 0;
			Iterator<ImportNode> it0 = imports.iterator();
			Iterator<ResourceNode> it1 = resources.iterator();
			Iterator<TemplateNode> it2 = templates.iterator();
			@Override
			public Iterator<Node> iterator() {
				return new Iterator<Node>() {

					@Override
					public boolean hasNext() {
						if (it == 0) {
							if (it0.hasNext()) return true;
							else it = 1;
						}
						if (it == 1) {
							if (it1.hasNext()) return true;
							else it = 2;
						}
						if (it == 2) {
							return it2.hasNext();
						}
						return false;
					}

					@Override
					public Node next() {
						if (it == 0) {
							return it0.next();
						} else if (it == 1) {
							return it1.next();
						} else {
							return it2.next();
						}
					}

					@Override
					public void remove() {
						throw new UnsupportedOperationException();
					}
					
				};
			}
		};
	}

	@Override
	protected String getXMLNodeName() {
		return "TemplateDefinitions";
	}

	@Override
	protected String getXMLAttributes() {
		return String.format("version=\"%s\"", version);
	}

}
